/*
 * Aeon [com.beskrajnost.aeon]
 *
 * This file is a part of the Aeon project and a property of Beskrajnost and may
 * not be copied, modified or distributed without a written permission,
 * contracted agreement or a license from the copyright holder.
 *
 * [c] 2008, Beskrajnost. All rights reserved.
 */

#ifndef __couple_hpp__
#define __couple_hpp__

#include <cmath> // Standard C++ math library header.

//! Top-level package.
namespace com
{
//! Sub-package.
namespace beskrajnost
{
//! Project package.
namespace aeon
{
	/*!
	 * @class
	 *    Couple
	 * @version
	 *    0.7.2:1
	 * @author
	 *    Beskrajnost
	 * @brief
	 *    Couple is a two-fold mathematical entity that supports basic geometric
	 *    functions such as dot-product or cross-product within its body.
	 */
	template<typename type_t>
	class Couple
	{
	public:
		//! Constructor. Initializes both of the components to zero.
		Couple();

		/*!
		 * Copy-constructor.
		 * @param
		 *    clsCouple A Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple(Couple<other_t> const &clCouple);

		/*!
		 * Constructor. Initializes both of the components to the same, given
		 * value.
		 * @param vValue
		 *    A value.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple(other_t const &vValue);

		/*!
		 * Constructor. Initializes components to given values.
		 * @param vA
		 *    A value for the X component.
		 * @param vB
		 *    A value for the Y component.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple(other_t const &vA, other_t const &vB);

		/*!
		 * Copy-assignment operator.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    A reference to this Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator =(Couple<other_t> const &clCouple);

		/*!
		 * Assignment operator. The given value is assigned to both of the
		 * components.
		 * @param vValue
		 *    A value.
		 * @return
		 *    A reference to this Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator =(other_t const &vValue);

		/*!
		 * Positive operator.
		 * @note
		 *    This operator is here for seamless-plug capability of Couple to
		 *    the arithmetical components of C. It really does nothing as you
		 *    can observe.
		 * @return
		 *    A copy of this Couple.
		 */
		Couple operator +() const;

		/*!
		 * Negative operator.
		 * @return A Couple with negative values of components of this Couple.
		 */
		Couple operator -() const;

		/*!
		 * Prefix increment operator.
		 * @return
		 *    A reference to this Couple.
		 */
		Couple &operator ++();

		/*!
		 * Postfix increment operator.
		 * @param nDummy
		 *    Dummy parameter specified by the C++ Standard to distinguish
		 *    between prefix and postfix version of these operators.
		 * @return
		 *    A copy of this Couple before the increment.
		 */
		Couple operator ++(int nDummy);

		/*!
		 * Prefix decrement operator.
		 * @return
		 *    A reference to this Couple.
		 */
		Couple &operator --();

		/*!
		 * Postfix decrement operator.
		 * @param nDummy
		 *    Dummy parameter specified by the C++ Standard to distinguish
		 *    between prefix and postfix version of these operators.
		 * @return
		 *    A copy of this Couple before the decrement.
		 */
		Couple operator --(int nDummy);

		/*!
		 * Addition operator. Adds the given Couple to this Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    Sum as a new Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator +(Couple<other_t> const &clCouple) const;

		/*!
		 * Addition operator. Adds the given value to X and Y components.
		 * @param vValue
		 *    A value.
		 * @return
		 *    Sum as a new Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator +(other_t const &vValue) const;

		/*!
		 * Subtraction operator. Subtracts the given Couple from this Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    Difference as a new Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator -(Couple<other_t> const &clCouple) const;

		/*!
		 * Subtraction operator. Subtracts the given value from X and Y
		 * components.
		 * @param vValue
		 *    A value.
		 * @return
		 *    Difference as a new Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator -(other_t const &vValue) const;

		/*!
		 * Multiplication operator. Multiplies this Couple by the given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    Product as a new Couple.
		 * @attention
		 *    This is not dot- or cross-product! This is a component-wise
		 *    multiplication.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator *(Couple<other_t> const &clCouple) const;

		/*!
		 * Multiplication operator. Multiplies X and Y components by the given
		 * value.
		 * @param vValue
		 *    A value.
		 * @return
		 *    Product as a new Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator *(other_t const &vValue) const;

		/*!
		 * Division operator. Divides this Couple by the given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    Quotient as a new Couple.
		 * @attention
		 *    This is not an inverse dot- or cross-product! This is a
		 *    component-wise division.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator /(Couple<other_t> const &clCouple) const;

		/*!
		 * Division operator. Divides X and Y components by the given value.
		 * @param vValue
		 *    A value.
		 * @return
		 *    Quotient as a new Couple.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> operator /(other_t const &vValue) const;

		/*!
		 * Addition-assignment operator. Adds the given Couple to this Couple
		 * and assigns the result to this Couple again.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    A reference to this Couple which is the sum.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator +=(Couple<other_t> const &clCouple);

		/*!
		 * Addition-assignment operator. Adds the given value to X and Y
		 * components and assigns the result to this Couple again.
		 * @param vValue
		 *    A value
		 * @return
		 *    A reference to this Couple which is the sum.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator +=(other_t const &vValue);

		/*!
		 * Subtraction-assignment operator. Subtracts the given Couple from this
		 * Couple and assigns the result to this Couple again.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    A reference to this Couple which is the difference.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator -=(Couple<other_t> const &clCouple);

		/*!
		 * Subtraction-assignment operator. Subtracts the given value from X and
		 * Y components and assigns the result to this Couple again.
		 * @param vValue
		 *    A value
		 * @return
		 *    A reference to this Couple which is the difference.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator -=(other_t const &vValue);

		/*!
		 * Multiplication-assignment operator. Multiplies this Couple by the
		 * given Couple and assigns the result to this Couple again.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    A reference to this Couple which is the product.
		 * @attention
		 *    This is not dot- or cross-product! This is a component-wise
		 *    multiplication.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator *=(Couple<other_t> const &clCouple);

		/*!
		 * Multiplication-assignment operator. Multiplies X and Y components by
		 * the given value and assigns the result to this Couple again.
		 * @param vValue
		 *    A value
		 * @return
		 *    A reference to this Couple which is the product.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator *=(other_t const &vValue);

		/*!
		 * Division-assignment operator. Divides this Couple by the given Couple
		 * and assigns the result to this Couple again.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    A reference to this Couple which is the product.
		 * @attention
		 *    This is not an inverse dot- or cross-product! This is a
		 *    component-wise division.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator /=(Couple<other_t> const &clCouple);

		/*!
		 * Division-assignment operator. Divides X and Y components by the given
		 * value and assigns the result to this Couple again.
		 * @param vValue
		 *    A value
		 * @return
		 *    A reference to this Couple which is the product.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		Couple<type_t> &operator /=(other_t const &vValue);

		/*!
		 * Subscript (random-access) operator.
		 * @param iIndex
		 *    An index value.
		 * @note
		 *    @c index_t must be capable of being used as an array index type.
		 * @note
		 *    This operator does not perform range check.
		 * @sa
		 *    @c at() for range-checked version of this operator.
		 */
		template<typename index_t>
		type_t &operator [](index_t iIndex);

		/*!
		 * Subscript (random-access) operator.
		 * @param Index
		 *    An index value.
		 * @note
		 *    @c index_t must be capable of being used as an array index type.
		 * @note
		 *    This is the const-safe version of the subscript operator.
		 * @note
		 *    This operator does not perform range check.
		 * @sa
		 *    @c at() for range-checked version of this operator.
		 */
		template<typename index_t>
		type_t const operator [](index_t iIndex) const;

		/*!
		 * Subscript (random-access) function.
		 * @param iIndex
		 *    An index value.
		 * @note
		 *    @c index_t must be capable of being used as an array index type.
		 * @note
		 *    This function performs range check.
		 */
		template<typename index_t>
		type_t &at(index_t iIndex);

		/*!
		 * Subscript (random-access) function.
		 * @param Index
		 *    An index value.
		 * @note
		 *    @c index_t must be capable of being used as an array index type.
		 * @note
		 *    This is the const-safe version of the subscript function.
		 * @note
		 *    This function performs range check.
		 */
		template<typename index_t>
		type_t const at(index_t iIndex) const;

		/*!
		 * Type cast operator. Casts from Couple to @c type_t pointer.
		 * @return
		 *    A pointer pointing to the beginning of the components array.
		 * @note
		 *    @c type_t must be convertible to @c other_t.
		 */
		template<typename other_t>
		operator other_t *();

		/*!
		 * Type cast operator. Casts from Couple to @c type_t pointer.
		 * @return
		 *    A constant pointer pointing to the beginning of the components
		 *    array.
		 * @note
		 *    This is the const-safe version of operator type_t *().
		 * @note
		 *    @c type_t must be convertible to @c other_t.
		 * @sa
		 *    @c operator type_t *()
		 */
		template<typename other_t>
		operator other_t const *() const;

		/*!
		 * Fetches the values for X and Y components from the bank that is
		 * pointed-to by the given iterator.
		 * @param itrIterator
		 *    A forward iterator pointing to the beginning of an array with two
		 *    or more elements.
		 * @attention
		 *    @c iterator_t must be guaranteed to be dereferencable within the
		 *    range of two elements.
		 * @note
		 *    Value type of @c iterator_t must be convertible to @c type_t.
		 */
		template<typename iterator_t>
		void fetch(iterator_t itrIterator);

		/*!
		 * Calculates the magnitude (length) of this Couple.
		 * @return
		 *   Magnitude of this Couple.
		 */
		type_t magnitude() const;

		/*!
		 * Calculates the length (magnitude) of this Couple.
		 * @return
		 *    Length of this Couple.
		 * @note
		 *    This function is an alias of @c magnitude().
		 */
		inline type_t length() const;

		/*!
		 * Normalizes this Couple.
		 * @attention
		 *    This function does not return a copy of the normalized Couple,
		 *    instead it directly normalizes this Couple by modifying its
		 *    components!
		 * @sa
		 *    aeon::math::normalize() for the version that doesn't directly
		 *    modify the components.
		 */
		void normalize();

		/*!
		 * Calculates the dot product of this Couple with the given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    Dot-product.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		type_t dot(Couple<other_t> const &clCouple) const;

		/*!
		 * Compares this Couple to the given Couple for logical equality.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    If both Couples are logically the same then @c true is returned,
		 *    otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator ==(Couple<other_t> const &clCouple) const;

		/*!
		 * Compares X and Y components to the given value for logical equality.
		 * @param vValue
		 *    A value.
		 * @return
		 *    If both components are logically equal to the given value then @c
		 *    true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator ==(other_t const &vValue) const;

		/*!
		 * Compares this Couple to the given Couple for logical inequality.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    If both Couples are not logically the same then @c true is
		 *    returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator !=(Couple<other_t> const &clCouple) const;

		/*!
		 * Compares X and Y components to the given value for logical
		 * inequality.
		 * @param vValue
		 *    A value.
		 * @return
		 *    If both components are not logically equal to the given value then
		 *    @c true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator !=(other_t const &vValue) const;

		/*!
		 * Smaller than operator. Checks if this Couple is smaller than the
		 * given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    If this Couple is smaller than the given Couple then @c true is
		 *    returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator <(Couple<other_t> const &clCouple) const;

		/*!
		 * Smaller than operator. Checks if X and Y components are smaller than
		 * the given value.
		 * @param vValue
		 *    A value.
		 * @return
		 *    If X and Y components are smaller than the given value then @c
		 *    true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator <(other_t const &vValue) const;

		/*!
		 * Greater than operator. Checks if this Couple is greater than the
		 * given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    If this Couple is greater than the given Couple then @c true is
		 *    returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator >(Couple<other_t> const &clCouple) const;

		/*!
		 * Greater than operator. Checks if X and Y components are greater than
		 * the given value.
		 * @param vValue
		 *    A value.
		 * @return
		 *    If X and Y components are greater than the given value then @c
		 *    true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator >(other_t const &vValue) const;

		/*!
		 * Smaller than or equal to operator. Checks if this Couple is smaller
		 * than or equal to the given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    If this Couple is smaller than or equal to the given Couple then
		 *    @c true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator <=(Couple<other_t> const &clCouple) const;

		/*!
		 * Smaller than or equal to operator. Checks if X and Y components are
		 * smaller than or equal to the given value.
		 * @param vValue
		 *    A value.
		 * @return
		 *    If X and Y components are smaller than or equal to the given value
		 *    then @c true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator <=(other_t const &vValue) const;

		/*!
		 * Greater than or equal to operator. Checks if this Couple is greater
		 * than or equal to the given Couple.
		 * @param clCouple
		 *    A Couple.
		 * @return
		 *    If this Couple is greater than or equal to the given Couple then
		 *    @c true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator >=(Couple<other_t> const &clCouple) const;

		/*!
		 * Greater than or equal to operator. Checks if X and Y components are
		 * greater than or equal to the given value.
		 * @param vValue
		 *    A value.
		 * @return
		 *    If X and Y components are greater than or equal to the given value
		 *    then @c true is returned, otherwise @c false is returned.
		 * @note
		 *    @c other_t must be convertible to @c type_t.
		 */
		template<typename other_t>
		bool operator >=(other_t const &vValue) const;

		//! This anonimous union maps an array onto X and Y components.
		union
		{
			//! Components package.
			struct
			{
				//! X component.
				type_t vX;

				//! Y component.
				type_t vY;
			};

			//! This array maps onto X and Y components.
			type_t avComponents[2];
		};
	};

	//! @see Couple::Couple()
	template<typename type_t>
	Couple<type_t>::Couple()
		: vX(0), vY(0)
	{
	}

	//! @see Couple::Couple()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>::Couple(Couple<other_t> const &clCouple)
		: vX(clCouple.vX), vY(clCouple.vY)
	{
	}

	//! @see Couple::Couple()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>::Couple(other_t const &vValue)
		: vX(vValue), vY(vValue)
	{
	}

	//! @see Couple::Couple()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>::Couple(other_t const &vA, other_t const &vB)
		: vX(vA), vY(vB)
	{
	}

	//! @see Couple::operator =()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator =(Couple<other_t> const &clCouple)
	{
		vX = clCouple.vX;
		vY = clCouple.vY;

		return *this;
	}

	//! @see Couple::operator =()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator =(other_t const &vValue)
	{
		vX = vValue;
		vY = vValue;

		return *this;
	}

	//! @see Couple::operator +()
	template<typename type_t>
	Couple<type_t> Couple<type_t>::operator +() const
	{
		return *this;
	}

	//! @see Couple::operator -()
	template<typename type_t>
	Couple<type_t> Couple<type_t>::operator -() const
	{
		return Couple<type_t>(-vX, -vY);
	}

	//! @see Couple::operator ++()
	template<typename type_t>
	Couple<type_t> &Couple<type_t>::operator ++()
	{
		++vX;
		++vY;

		return *this;
	}

	//! @see Couple::operator ++()
	template<typename type_t>
	Couple<type_t> Couple<type_t>::operator ++(int nDummy)
	{
		Couple<type_t> clReturn(*this);

		++vX;
		++vY;

		return clReturn;
	}

	//! @see Couple::operator --()
	template<typename type_t>
	Couple<type_t> &Couple<type_t>::operator --()
	{
		--vX;
		--vY;

		return *this;
	}

	//! @see Couple::operator --()
	template<typename type_t>
	Couple<type_t> Couple<type_t>::operator --(int nDummy)
	{
		Couple<type_t> clReturn(*this);

		--vX;
		--vY;

		return clReturn;
	}

	//! @see Couple::operator +()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>
		Couple<type_t>::operator +(Couple<other_t> const &clCouple) const
	{
		return Couple<type_t>(vX + clCouple.vX, vY + clCouple.vY);
	}

	//! @see Couple::operator +()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> Couple<type_t>::operator +(other_t const &vValue) const
	{
		return Couple<type_t>(vX + vValue, vY + vValue);
	}

	//! @see Couple::operator -()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>
		Couple<type_t>::operator -(Couple<other_t> const &clCouple) const
	{
		return Couple<type_t>(vX - clCouple.vX, vY - clCouple.vY);
	}

	//! @see Couple::operator -()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> Couple<type_t>::operator -(other_t const &vValue) const
	{
		return Couple<type_t>(vX - vValue, vY - vValue);
	}

	//! @see Couple::operator *()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>
		Couple<type_t>::operator *(Couple<other_t> const &clCouple) const
	{
		return Couple<type_t>(vX * clCouple.vX, vY * clCouple.vY);
	}

	//! @see Couple::operator *()
		template<typename type_t>
			template<typename other_t>
	Couple<type_t> Couple<type_t>::operator *(other_t const &vValue) const
	{
		return Couple<type_t>(vX * vValue, vY * vValue);
	}

	//! @see Couple::operator /()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>
		Couple<type_t>::operator /(Couple<other_t> const &clCouple) const
	{
		return Couple<type_t>(vX / clCouple.vX, vY / clCouple.vY);
	}

	//! @see Couple::operator /()
		template<typename type_t>
			template<typename other_t>
	Couple<type_t> Couple<type_t>::operator /(other_t const &vValue) const
	{
		return Couple<type_t>(vX / vValue, vY / vValue);
	}

	//! @see Couple::operator +=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator +=(Couple<other_t> const &clCouple)
	{
		vX += clCouple.vX;
		vY += clCouple.vY;

		return *this;
	}

	//! @see Couple::operator +=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator +=(other_t const &vValue)
	{
		vX += vValue;
		vY += vValue;

		return *this;
	}

	//! @see Couple::operator -=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator -=(Couple<other_t> const &clCouple)
	{
		vX -= clCouple.vX;
		vY -= clCouple.vY;

		return *this;
	}

	//! @see Couple::operator -=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator -=(other_t const &vValue)
	{
		vX -= vValue;
		vY -= vValue;

		return *this;
	}

	//! @see Couple::operator *=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator *=(Couple<other_t> const &clCouple)
	{
		vX *= clCouple.vX;
		vY *= clCouple.vY;

		return *this;
	}

	//! @see Couple::operator *=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator *=(other_t const &vValue)
	{
		vX *= vValue;
		vY *= vValue;

		return *this;
	}

	//! @see Couple::operator /=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator /=(Couple<other_t> const &clCouple)
	{
		vX /= clCouple.vX;
		vY /= clCouple.vY;

		return *this;
	}

	//! @see Couple::operator /=()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t> &Couple<type_t>::operator /=(other_t const &vValue)
	{
		vX /= vValue;
		vY /= vValue;

		return *this;
	}

	//! @see Couple::operator []()
	template<typename type_t>
		template<typename index_t>
	type_t &Couple<type_t>::operator [](index_t iIndex)
	{
		return avComponents[iIndex];
	}

	//! @see Couple::operator []()
	template<typename type_t>
		template<typename index_t>
	type_t const Couple<type_t>::operator [](index_t iIndex) const
	{
		return static_cast<type_t const>(avComponents[iIndex]);
	}

	//! @see Couple::at()
	template<typename type_t>
		template<typename index_t>
	type_t &Couple<type_t>::at(index_t iIndex)
	{
		if(iIndex < 0 || iIndex > 1)
			iIndex = 0;

		return avComponents[iIndex];
	}

	//! @see Couple::at()
	template<typename type_t>
		template<typename index_t>
	type_t const Couple<type_t>::at(index_t iIndex) const
	{
		if(iIndex < 0 || iIndex > 1)
			iIndex = 0;

		return static_cast<type_t const>(avComponents[iIndex]);
	}

	//! @see Couple::operator type_t *()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>::operator other_t *()
	{
		return static_cast<other_t *>(avComponents);
	}

	//! @see Couple::operator type_t *()
	template<typename type_t>
		template<typename other_t>
	Couple<type_t>::operator other_t const *() const
	{
		return static_cast<other_t const *>(avComponents);
	}

	//! @see Couple::fetch()
	template<typename type_t>
		template<typename iterator_t>
	void Couple<type_t>::fetch(iterator_t itrIterator)
	{
		vX = *itrIterator;

		++itrIterator;

		vY = *itrIterator;
	}

	//! @see Couple::magnitude()
	template<typename type_t>
	type_t Couple<type_t>::magnitude() const
	{
		return std::sqrt(vX * vX + vY * vY);
	}

	//! @see Couple::magnitude()
	template<typename type_t>
	inline type_t Couple<type_t>::length() const
	{
		return magnitude();
	}

	//! @see Couple::normalize()
	template<typename type_t>
	void Couple<type_t>::normalize()
	{
		type_t vMagnitude = magnitude();

		vX /= vMagnitude;
		vY /= vMagnitude;
	}

	//! @see Couple::dot()
	template<typename type_t>
		template<typename other_t>
	type_t Couple<type_t>::dot(Couple<other_t> const &clCouple) const
	{
		return (vX * clCouple.vX + vY * clCouple.vY);
	}

	//! @see Couple::operator ==().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator ==(Couple<other_t> const &clCouple) const
	{
		return (vX == clCouple.vX && vY == clCouple.vY);
	}

	//! @see Couple::operator ==().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator ==(other_t const &vValue) const
	{
		return (vX == vValue && vY == vValue);
	}

	//! @see Couple::operator !=().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator !=(Couple<other_t> const &clCouple) const
	{
		return (vX != clCouple.vX || vY != clCouple.vY);
	}

	//! @see Couple::operator !=().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator !=(other_t const &vValue) const
	{
		return (vX != vValue || vY != vValue);
	}

	//! @see Couple::operator <().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator <(Couple<other_t> const &clCouple) const
	{
		return (vX < clCouple.vX && vY < clCouple.vY);
	}

	//! @see Couple::operator <().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator <(other_t const &vValue) const
	{
		return (vX < vValue && vY < vValue);
	}

	//! @see Couple::operator >().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator >(Couple<other_t> const &clCouple) const
	{
		return (vX > clCouple.vX && vY > clCouple.vY);
	}

	//! @see Couple::operator >().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator >(other_t const &vValue) const
	{
		return (vX > vValue && vY > vValue);
	}

	//! @see Couple::operator <=().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator <=(Couple<other_t> const &clCouple) const
	{
		return (vX <= clCouple.vX && vY <= clCouple.vY);
	}

	//! @see Couple::operator <=().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator <=(other_t const &vValue) const
	{
		return (vX <= vValue && vY <= vValue);
	}

	//! @see Couple::operator >=().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator >=(Couple<other_t> const &clCouple) const
	{
		return (vX >= clCouple.vX && vY >= clCouple.vY);
	}

	//! @see Couple::operator >=().
	template<typename type_t>
		template<typename other_t>
	bool Couple<type_t>::operator >=(other_t const &vValue) const
	{
		return (vX >= vValue && vY >= vValue);
	}
} // namespace aeon
} // namespace beskrajnost
} // namespace com

#endif // __couple_hpp__
